package com.zenithmind.news.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.utils.BeanCopyUtils;
import com.zenithmind.news.mapper.NewsMapper;
import com.zenithmind.news.pojo.dto.NewsCreateDTO;
import com.zenithmind.news.pojo.entity.News;
import com.zenithmind.news.pojo.vo.NewsVO;
import com.zenithmind.news.service.NewsService;
import com.zenithmind.news.service.NewsCacheService;
import com.zenithmind.news.service.NewsPushService;
import com.zenithmind.news.service.UserBehaviorService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 新闻基础服务实现类 - 遵循单一职责原则
 * 只负责新闻的基本CRUD操作，其他职责分离到专门的服务类
 *
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class NewsServiceImpl extends ServiceImpl<NewsMapper, News> implements NewsService {

    private final NewsMapper newsMapper;
    private final UserBehaviorService userBehaviorService;
    private final NewsCacheService newsCacheService;
    private final NewsPushService newsPushService;
    private final ObjectMapper objectMapper;

    private static final long CACHE_EXPIRE_TIME = 30; // 缓存过期时间（分钟）

    @Override
    @Transactional(rollbackFor = Exception.class)
    public NewsVO createNews(NewsCreateDTO createDTO) {
        // 获取当前用户信息
        String currentUserId = UserContext.getUserId();
        String currentUserName = UserContext.getUsername();
        
        if (!StringUtils.hasText(currentUserId)) {
            throw new BusinessException("用户未登录");
        }

        // 创建新闻实体
        News news = new News();
        news.setTitle(createDTO.getTitle());
        news.setSummary(createDTO.getSummary());
        news.setContent(createDTO.getContent());
        news.setSource(createDTO.getSource());
        news.setSourceUrl(createDTO.getSourceUrl());
        news.setAuthor(createDTO.getAuthor());
        news.setCategoryId(createDTO.getCategoryId());
        news.setType(createDTO.getType());
        news.setPriority(createDTO.getPriority());
        news.setIsTop(createDTO.getIsTop());
        news.setIsRecommend(createDTO.getIsRecommend());
        news.setPublisherId(currentUserId);
        news.setPublisherName(currentUserName);
        news.setSortOrder(createDTO.getSortOrder());

        // 处理标签和关键词
        if (createDTO.getTags() != null && !createDTO.getTags().isEmpty()) {
            try {
                news.setTags(objectMapper.writeValueAsString(createDTO.getTags()));
            } catch (JsonProcessingException e) {
                log.error("标签序列化失败", e);
            }
        }
        
        if (createDTO.getKeywords() != null && !createDTO.getKeywords().isEmpty()) {
            try {
                news.setKeywords(objectMapper.writeValueAsString(createDTO.getKeywords()));
            } catch (JsonProcessingException e) {
                log.error("关键词序列化失败", e);
            }
        }

        // 处理图片
        news.setCoverImage(createDTO.getCoverImage());
        if (createDTO.getImages() != null && !createDTO.getImages().isEmpty()) {
            try {
                news.setImages(objectMapper.writeValueAsString(createDTO.getImages()));
            } catch (JsonProcessingException e) {
                log.error("图片列表序列化失败", e);
            }
        }

        // 注意：统计数据现在由NewsStatistics实体单独管理

        // 设置状态
        if (createDTO.getPublishNow() == 1) {
            news.setStatus(1); // 已发布
            news.setPublishTime(LocalDateTime.now());
        } else {
            news.setStatus(0); // 草稿
        }

        // 保存新闻
        boolean saved = save(news);
        if (!saved) {
            throw new BusinessException("创建新闻失败");
        }

        // 如果是发布状态，进行实时推送
        if (news.getStatus() == 1) {
            newsPushService.pushNews(news);
        }

        log.info("用户 {} 创建了新闻 {}", currentUserName, news.getTitle());
        
        return convertToVO(news, currentUserId);
    }

    @Override
    public PageResult<NewsVO> getNewsPage(Long current, Long size, String categoryId, 
                                         Integer status, Integer type, String keyword,
                                         LocalDateTime startTime, LocalDateTime endTime) {
        Page<News> page = new Page<>(current, size);
        IPage<News> newsPage = newsMapper.selectNewsPage(page, categoryId, status, type, 
                                                         keyword, startTime, endTime);
        
        String currentUserId = UserContext.getUserId();
        List<NewsVO> records = newsPage.getRecords().stream()
                .map(news -> convertToVO(news, currentUserId))
                .toList();
        
        return new PageResult<>(records, newsPage.getTotal(), newsPage.getCurrent(), newsPage.getSize());
    }

    @Override
    public NewsVO getNewsById(String id, String userId) {
        // 先从缓存获取
        NewsVO cachedNews = newsCacheService.getCachedNewsDetail(id);
        if (cachedNews != null) {
            // 记录用户行为
            if (StringUtils.hasText(userId)) {
                userBehaviorService.recordBehavior(userId, id, 1, null, 1.0);
                // 异步增加阅读量
                newsCacheService.incrementViewCount(id);
            }
            return cachedNews;
        }

        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        NewsVO newsVO = convertToVO(news, userId);

        // 缓存新闻详情
        newsCacheService.cacheNewsDetail(id, newsVO, CACHE_EXPIRE_TIME, TimeUnit.MINUTES);

        // 记录用户行为
        if (StringUtils.hasText(userId)) {
            userBehaviorService.recordBehavior(userId, id, 1, null, 1.0);
            // 异步增加阅读量
            newsCacheService.incrementViewCount(id);
        }

        return newsVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateNews(String id, NewsCreateDTO updateDTO) {
        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        // 检查权限
        String currentUserId = UserContext.getUserId();
        if (!news.getPublisherId().equals(currentUserId)) {
            throw new BusinessException("无权限修改此新闻");
        }

        // 更新新闻信息
        news.setTitle(updateDTO.getTitle());
        news.setSummary(updateDTO.getSummary());
        news.setContent(updateDTO.getContent());
        news.setSource(updateDTO.getSource());
        news.setSourceUrl(updateDTO.getSourceUrl());
        news.setAuthor(updateDTO.getAuthor());
        news.setCategoryId(updateDTO.getCategoryId());
        news.setType(updateDTO.getType());
        news.setPriority(updateDTO.getPriority());
        news.setIsTop(updateDTO.getIsTop());
        news.setIsRecommend(updateDTO.getIsRecommend());
        news.setSortOrder(updateDTO.getSortOrder());

        // 处理标签和关键词
        if (updateDTO.getTags() != null) {
            try {
                news.setTags(objectMapper.writeValueAsString(updateDTO.getTags()));
            } catch (JsonProcessingException e) {
                log.error("标签序列化失败", e);
            }
        }
        
        if (updateDTO.getKeywords() != null) {
            try {
                news.setKeywords(objectMapper.writeValueAsString(updateDTO.getKeywords()));
            } catch (JsonProcessingException e) {
                log.error("关键词序列化失败", e);
            }
        }

        // 处理图片
        news.setCoverImage(updateDTO.getCoverImage());
        if (updateDTO.getImages() != null) {
            try {
                news.setImages(objectMapper.writeValueAsString(updateDTO.getImages()));
            } catch (JsonProcessingException e) {
                log.error("图片列表序列化失败", e);
            }
        }

        boolean updated = updateById(news);
        if (updated) {
            // 清除缓存
            clearNewsCache(id);
            log.info("用户 {} 更新了新闻 {}", UserContext.getUsername(), news.getTitle());
        }
        
        return updated;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteNews(String id) {
        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        // 检查权限
        String currentUserId = UserContext.getUserId();
        if (!news.getPublisherId().equals(currentUserId)) {
            throw new BusinessException("无权限删除此新闻");
        }

        boolean deleted = removeById(id);
        if (deleted) {
            // 清除缓存
            clearNewsCache(id);
            log.info("用户 {} 删除了新闻 {}", UserContext.getUsername(), news.getTitle());
        }
        
        return deleted;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean publishNews(String id) {
        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        // 检查权限
        String currentUserId = UserContext.getUserId();
        if (!news.getPublisherId().equals(currentUserId)) {
            throw new BusinessException("无权限发布此新闻");
        }

        news.setStatus(1); // 已发布
        news.setPublishTime(LocalDateTime.now());
        
        boolean updated = updateById(news);
        if (updated) {
            // 清除缓存
            clearNewsCache(id);
            // 实时推送
            newsPushService.pushNews(news);
            log.info("用户 {} 发布了新闻 {}", UserContext.getUsername(), news.getTitle());
        }
        
        return updated;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean unpublishNews(String id) {
        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        // 检查权限
        String currentUserId = UserContext.getUserId();
        if (!news.getPublisherId().equals(currentUserId)) {
            throw new BusinessException("无权限下架此新闻");
        }

        news.setStatus(2); // 已下架
        
        boolean updated = updateById(news);
        if (updated) {
            // 清除缓存
            clearNewsCache(id);
            log.info("用户 {} 下架了新闻 {}", UserContext.getUsername(), news.getTitle());
        }
        
        return updated;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateNewsStatus(String id, String status) {
        log.info("更新新闻状态: {} -> {}", id, status);

        News news = getById(id);
        if (news == null) {
            throw new BusinessException("新闻不存在");
        }

        // 检查权限
        String currentUserId = UserContext.getUserId();
        if (!news.getPublisherId().equals(currentUserId)) {
            throw new BusinessException("无权限修改此新闻状态");
        }

        // 根据状态字符串设置状态值
        Integer statusValue = switch (status.toUpperCase()) {
            case "DRAFT" -> 0;
            case "PUBLISHED" -> 1;
            case "UNPUBLISHED" -> 2;
            case "REVIEWING" -> 3;
            case "REJECTED" -> 4;
            default -> throw new BusinessException("无效的状态值: " + status);
        };

        news.setStatus(statusValue);

        boolean updated = updateById(news);
        if (updated) {
            // 清除缓存
            clearNewsCache(id);
            log.info("用户 {} 更新了新闻 {} 的状态为 {}", UserContext.getUsername(), news.getTitle(), status);
        }

        return updated;
    }



    /**
     * 转换为VO
     */
    private NewsVO convertToVO(News news, String userId) {
        NewsVO vo = BeanCopyUtils.copyBean(news, NewsVO.class);
        
        // 设置额外信息
        setAdditionalInfo(vo);
        
        // 解析JSON字段
        parseJsonFields(vo, news);
        
        // 设置用户相关信息
        if (StringUtils.hasText(userId)) {
            setUserRelatedInfo(vo, userId);
        }
        
        return vo;
    }

    /**
     * 设置额外信息
     */
    private void setAdditionalInfo(NewsVO vo) {
        // 设置类型名称
        switch (vo.getType()) {
            case 1 -> vo.setTypeName("原创");
            case 2 -> vo.setTypeName("转载");
            case 3 -> vo.setTypeName("爬虫");
            default -> vo.setTypeName("未知");
        }
        
        // 设置状态名称
        switch (vo.getStatus()) {
            case 0 -> vo.setStatusName("草稿");
            case 1 -> vo.setStatusName("已发布");
            case 2 -> vo.setStatusName("已下架");
            case 3 -> vo.setStatusName("审核中");
            case 4 -> vo.setStatusName("审核失败");
            default -> vo.setStatusName("未知");
        }
        
        // 设置优先级名称
        switch (vo.getPriority()) {
            case 1 -> vo.setPriorityName("低");
            case 2 -> vo.setPriorityName("中");
            case 3 -> vo.setPriorityName("高");
            case 4 -> vo.setPriorityName("紧急");
            default -> vo.setPriorityName("未知");
        }
        
        // 设置相对时间
        if (vo.getPublishTime() != null) {
            vo.setRelativeTime(getRelativeTime(vo.getPublishTime()));
        }
    }

    /**
     * 解析JSON字段
     */
    private void parseJsonFields(NewsVO vo, News news) {
        try {
            if (StringUtils.hasText(news.getTags())) {
                vo.setTags(objectMapper.readValue(news.getTags(), List.class));
            }
            if (StringUtils.hasText(news.getKeywords())) {
                vo.setKeywords(objectMapper.readValue(news.getKeywords(), List.class));
            }
            if (StringUtils.hasText(news.getImages())) {
                vo.setImages(objectMapper.readValue(news.getImages(), List.class));
            }
        } catch (JsonProcessingException e) {
            log.error("解析JSON字段失败", e);
        }
    }

    /**
     * 设置用户相关信息
     */
    private void setUserRelatedInfo(NewsVO vo, String userId) {
        // 这里可以查询用户是否点赞、收藏等
        // 为了简化，暂时设置为false
        vo.setIsLiked(false);
        vo.setIsFavorited(false);
    }

    /**
     * 获取相对时间
     */
    private String getRelativeTime(LocalDateTime publishTime) {
        LocalDateTime now = LocalDateTime.now();
        long minutes = ChronoUnit.MINUTES.between(publishTime, now);
        
        if (minutes < 1) {
            return "刚刚";
        } else if (minutes < 60) {
            return minutes + "分钟前";
        } else if (minutes < 1440) {
            return (minutes / 60) + "小时前";
        } else {
            return (minutes / 1440) + "天前";
        }
    }

    /**
     * 清除新闻缓存
     */
    private void clearNewsCache(String newsId) {
        newsCacheService.evictNewsCache(newsId);
    }

    // 其他方法的实现...
    @Override
    public Boolean reviewNews(String id, Boolean approved, String comment) {
        // 实现审核逻辑
        return true;
    }




}
